package com.xbongbong.paas.service.dynamic.crm.strategy.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.elasticsearch.model.PaasEsModel;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.log.constant.CrmLogMemoConstant;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.service.dynamic.crm.strategy.AbstractDynamicStrategy;
import com.xbongbong.paas.service.dynamic.crm.strategy.SmsDynamicStrategy;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.TelephoneMaskUtil;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.customercommunicate.pojo.dto.DynamicDTO;
import com.xbongbong.pro.dynamic.pojo.dto.DynamicSmsDTO;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.SmsReplyEntity;
import com.xbongbong.saas.domain.entity.SmsStatusEntity;
import com.xbongbong.saas.enums.ProjectLogEnum;
import com.xbongbong.saas.enums.SmsStatusEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ContactEnum;
import com.xbongbong.saas.enums.business.CustomerManagementEnum;
import com.xbongbong.saas.model.IndexTypeModel;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.UserModel;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 *短信往来
 *
 *@author weijianxun
 */
@Service("smsDynamicStrategyImpl")
public class SmsDynamicStrategyImpl extends AbstractDynamicStrategy implements SmsDynamicStrategy {


    private final Logger LOG = LoggerFactory.getLogger(SmsDynamicStrategyImpl.class);

    // private static final Map<String, Integer> refTextToLogTypeMap = new HashMap<>();
    // static {
    // }

    @Resource
    private PaasEsModel paasEsModel;
    @Resource
    private UserModel userModel;
    @Resource
    private IndexTypeModel indexTypeModel;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;

    @Override
    public List<Integer> type() {
        // UNKNOWN 适用于回复信息
        return Arrays.asList(XbbRefTypeEnum.CONTACT.getCode(), XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), XbbRefTypeEnum.UNKNOWN.getCode());
    }

    @Override
    @Async("dynamicThreadPool")
    public void send(DynamicSmsDTO dynamicSmsDTO) {
        try {
            List<SmsStatusEntity> smsStatusEntities = dynamicSmsDTO.getSmsStatusEntities();
            if (CollectionUtils.isNotEmpty(smsStatusEntities)) {
                Map<String, List<SmsStatusEntity>> corpidToSmsMap = smsStatusEntities.stream().filter(item -> StringUtils.isNotEmpty(item.getMobile()) && Objects.equals(SmsStatusEnum.SEND_ING.getCode(), item.getStatus()))
                        .collect(Collectors.groupingBy(SmsStatusEntity::getCorpid));

                /// 测试用例，不过滤发送失败的信息
//                Map<String, List<SmsStatusEntity>> corpidToSmsMap = smsStatusEntities.stream().filter(item -> StringUtils.isNotEmpty(item.getMobile()))
//                        .collect(Collectors.groupingBy(SmsStatusEntity::getCorpid));

                List<DynamicDTO> insertDynamicDTOS = new ArrayList<>();
                for (Map.Entry<String, List<SmsStatusEntity>> sms : corpidToSmsMap.entrySet()) {
                    String corpid = sms.getKey();
                    List<SmsStatusEntity> entities = sms.getValue();
                    Set<String> mobiles = new HashSet<>(entities.size());
                    for (SmsStatusEntity smsStatusEntity : entities) {
                        if (smsStatusEntity.getMobile().contains(StringConstant.COMMA)) {
                            String[] ms = smsStatusEntity.getMobile().split(StringConstant.COMMA);
                            mobiles.addAll(Arrays.asList(ms));
                        } else {
                            mobiles.add(smsStatusEntity.getMobile());
                        }
                    }
                    Map<String, PaasFormDataEntityExt> mobileToCustomerInfoMap = getCustomerMobileToCustomerInfoMap(corpid, mobiles);
                    sendDynamic(corpid, entities, insertDynamicDTOS, mobileToCustomerInfoMap, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
                    Map<String, PaasFormDataEntityExt> mobileToContactInfoMap = getContactMobileToContactInfoMap(corpid, mobiles);
                    sendDynamic(corpid, entities, insertDynamicDTOS, mobileToContactInfoMap, XbbRefTypeEnum.CONTACT.getCode());
                }
                insertDynamicAndDtoIncludeCorpid(insertDynamicDTOS, "短信发送动态失败");
            }
        } catch (Exception e) {
            LOG.error("com.xbongbong.paas.service.dynamic.crm.strategy.impl.SmsDynamicStrategyImpl.send", e);
        }

    }

    @Override
    @Async("dynamicThreadPool")
    public void reply(DynamicSmsDTO dynamicSmsDTO) {
        try {
            List<SmsReplyEntity> smsReplyEntities = dynamicSmsDTO.getSmsReplyEntities();
            if (CollectionUtils.isNotEmpty(smsReplyEntities)) {
                List<DynamicDTO> insertDynamicDTOS = new ArrayList<>();
                Map<String, List<SmsReplyEntity>> corpIdToSmsMap = smsReplyEntities.stream().collect(Collectors.groupingBy(SmsReplyEntity::getCorpid));
                for (Map.Entry<String, List<SmsReplyEntity>> sms : corpIdToSmsMap.entrySet()) {
                    String corpid = sms.getKey();
                    List<SmsReplyEntity> entities = sms.getValue();
                    Set<String> mobiles = new HashSet<>(entities.size());
                    for (SmsReplyEntity smsReplyEntity : entities) {
                        if (smsReplyEntity.getMobile().contains(StringConstant.COMMA)) {
                            String[] ms = smsReplyEntity.getMobile().split(StringConstant.COMMA);
                            mobiles.addAll(Arrays.asList(ms));
                        } else {
                            mobiles.add(smsReplyEntity.getMobile());
                        }
                    }
                    Map<String, PaasFormDataEntityExt> mobileToContactInfoMap = getContactMobileToContactInfoMap(corpid, mobiles);
                    replyDynamic(corpid, entities, insertDynamicDTOS, mobileToContactInfoMap, XbbRefTypeEnum.CONTACT.getCode());
                    Map<String, PaasFormDataEntityExt> mobileToCustomerInfoMapInfoMap = getCustomerMobileToCustomerInfoMap(corpid, mobiles);
                    replyDynamic(corpid, entities, insertDynamicDTOS, mobileToCustomerInfoMapInfoMap, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
                }
                insertDynamicAndDtoIncludeCorpid(insertDynamicDTOS, "短信回复动态失败");
            }
        } catch (Exception e) {
            LOG.error("com.xbongbong.paas.service.dynamic.crm.strategy.impl.SmsDynamicStrategyImpl.reply", e);
        }

    }


    private Map<String, PaasFormDataEntityExt> getContactMobileToContactInfoMap(String corpid, Set<String> mobiles) throws XbbException {
        return getMobileToPaasFormDataMap(corpid, mobiles, XbbRefTypeEnum.CONTACT.getCode(), ContactEnum.PHONE.getAttr());
    }

    private Map<String, PaasFormDataEntityExt> getCustomerMobileToCustomerInfoMap(String corpid, Set<String> mobiles) throws XbbException {
        return getMobileToPaasFormDataMap(corpid, mobiles, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), CustomerManagementEnum.PHONE.getAttr());
    }

    private Map<String, PaasFormDataEntityExt> getMobileToPaasFormDataMap(String corpid, Set<String> mobiles, Integer businessType, String phoneAttr) throws XbbException {
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put(StringConstant.CORPID, corpid);
        params.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        Map<String, List> mobileMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        mobileMap.put("data." + phoneAttr + ".text_2.keyword", new ArrayList(mobiles));
        params.put("should", mobileMap);
        IndexTypeEnum indexTypeEnum = indexTypeModel.getIndexType(corpid, businessType, SaasMarkEnum.SAAS.getCode());
        List<PaasFormDataEntityExt> paasFormData = paasEsModel.selectByCondition(businessType, null, params,indexTypeEnum);
        // Set<Long> formIds = paasFormData.stream().map(PaasFormDataEntityExt::getFormId).collect(Collectors.toSet());
        // Map<Long, PaasFormEntity> formIdToPaasFormMap = proFormHelp.getPaasFormList(corpid, businessType, formIds).stream().collect(Collectors.toMap(PaasFormEntity::getId, item -> item));
        Map<String, PaasFormDataEntityExt> mobileToPaasFormDataMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (PaasFormDataEntityExt paasFormDataEntityExt : paasFormData) {
            JSONObject data = paasFormDataEntityExt.getData();
            JSONArray phone = data.getJSONArray(phoneAttr);
            for (JSONObject mobile : phone.toJavaList(JSONObject.class)) {
                mobileToPaasFormDataMap.put(mobile.getString("text_2"), paasFormDataEntityExt);
            }
            // PaasFormEntity paasFormEntity = formIdToPaasFormMap.get(paasFormDataEntityExt.getFormId());
            // if (Objects.nonNull(paasFormEntity)) {
            //     paasFormDataEntityExt.setBusinessType(paasFormEntity.getBusinessType());
            // }
        }
        return mobileToPaasFormDataMap;
    }

    private void replyDynamic(String corpid, List<SmsReplyEntity> smsReplyEntities, List<DynamicDTO> dynamicDTOS, Map<String, PaasFormDataEntityExt> mobileToPaasFormMap, Integer businessType) {
        Set<String> senderIds = smsReplyEntities.stream().map(SmsReplyEntity::getSenderId).collect(Collectors.toSet());
        // 发送人就是最后一个给客户或客户联系人发短信的人
        Map<String, UserEntity> userIdToUserMap = userModel.getByUserIdIn(corpid, senderIds, false).stream().collect(Collectors.toMap(UserEntity::getUserId, item -> item));
        for (SmsReplyEntity smsReplyEntity : smsReplyEntities) {
            String mobile = smsReplyEntity.getMobile();
            UserEntity userEntity = userIdToUserMap.get(smsReplyEntity.getSenderId());
            if (mobile.contains(StringConstant.COMMA)) {
                String[] phones = mobile.split(StringConstant.COMMA);
                for (String phone : phones) {
                    // creatorId就存为被客户回复的用户id吧
                    fillReplyDynamic(corpid, dynamicDTOS, mobileToPaasFormMap.get(phone), smsReplyEntity.getSenderId(), smsReplyEntity.getReplyName(), userEntity.getName(), phone, CrmLogMemoConstant.DYNAMIC_USER_REPLY_SMS, smsReplyEntity.getContent(), smsReplyEntity.getReplyTime(), businessType);
                }
            } else {
                fillReplyDynamic(corpid, dynamicDTOS, mobileToPaasFormMap.get(mobile), smsReplyEntity.getSenderId(), smsReplyEntity.getReplyName(), userEntity.getName(), mobile, CrmLogMemoConstant.DYNAMIC_USER_REPLY_SMS, smsReplyEntity.getContent(), smsReplyEntity.getReplyTime(), businessType);
            }
        }
    }

    private void sendDynamic(String corpid, List<SmsStatusEntity> smsStatusEntities, List<DynamicDTO> dynamicDTOS, Map<String, PaasFormDataEntityExt> mobileToPaasFormMap,Integer businessType) {
        for (SmsStatusEntity smsStatusEntity : smsStatusEntities) {
            String mobile = smsStatusEntity.getMobile();
            if (mobile.contains(StringConstant.COMMA)) {
                String[] phones = mobile.split(StringConstant.COMMA);
                for (String phone : phones) {
                    fillSendDynamic(corpid, dynamicDTOS, mobileToPaasFormMap.get(phone), smsStatusEntity.getUserId(), smsStatusEntity.getSender(), phone, CrmLogMemoConstant.DYNAMIC_USER_SEND_SMS, smsStatusEntity.getContent(), smsStatusEntity.getSendTime(), businessType);
                }
            } else {
                fillSendDynamic(corpid, dynamicDTOS, mobileToPaasFormMap.get(mobile), smsStatusEntity.getUserId(), smsStatusEntity.getSender(), mobile, CrmLogMemoConstant.DYNAMIC_USER_SEND_SMS, smsStatusEntity.getContent(), smsStatusEntity.getSendTime(), businessType);
            }
        }
    }

    private void fillSendDynamic(String corpid, List<DynamicDTO> dynamicDTOS, PaasFormDataEntityExt paasFormData, String creatorId, String sendName, String phone, String memo, String content, Long time, Integer businessType) {
        if (Objects.isNull(paasFormData)) {
            return;
        }
        JSONObject data = paasFormData.getData();
        XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(businessType);
        try {
            if (Objects.equals(xbbRefTypeEnum, XbbRefTypeEnum.CUSTOMER_MANAGEMENT) || Objects.equals(xbbRefTypeEnum, XbbRefTypeEnum.CONTACT)) {
                PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(paasFormData.getFormId(), corpid);
                Map<String, FieldAttrEntity> paasExplainMap = ExplainUtil.getExplainMap(paasFormExplainEntity.getExplains(), null);
                // CustomerManagementEnum.PHONE.getAttr() ContactEnum.PHONE.getAttr()
                FieldAttrEntity fieldAttr = paasExplainMap.get("subForm_1");
                if (Objects.nonNull(fieldAttr)) {
                    FieldAttrEntity phoneField = fieldAttr.getSubForm().getItems().stream().filter(item -> Objects.equals(item.getAttr(), "text_2")).findFirst().orElse(null);
                    // 开启了电话掩码功能才需要处理
                    if (Objects.nonNull(phoneField) && Objects.equals(phoneField.getIsMaskTelephone(), BasicConstant.ONE)) {
                        phone = TelephoneMaskUtil.maskTelephone(phone);
                    }
                }
            }
        } catch (Exception e) {
            LOG.error("SmsDynamicStrategyImpl.fillSendDynamic", e);
        }
        switch (xbbRefTypeEnum) {
            case CUSTOMER_MANAGEMENT:
                Long customerId = paasFormData.getId();
                String customerName = data.getString(CustomerManagementEnum.NAME.getAttr());
                customerName = Objects.nonNull(customerName) ? customerName : "";
                DynamicDTO dynamicDTO = initDynamicDTO(creatorId, memo, ProjectLogEnum.CUSTOMER_SMS.getSubType(), DynamicDTO.initMemoHolder(sendName, customerName + ": " + phone, content), null, null, customerId);
                dynamicDTO.setAddTime(time);
                dynamicDTO.setCorpid(corpid);
                dynamicDTOS.add(dynamicDTO);
                break;
            case CONTACT:
                Long contactId = paasFormData.getId();
                String contactName = data.getString(ContactEnum.NAME.getAttr());
                contactName = Objects.nonNull(contactName) ? contactName : "";
                DynamicDTO dynamicdto = initDynamicDTO(creatorId, memo, ProjectLogEnum.CONTACT_SMS.getSubType(), DynamicDTO.initMemoHolder(sendName, contactName + ": " + phone, content), null, null, contactId);
                dynamicdto.setAddTime(time);
                dynamicdto.setCorpid(corpid);
                dynamicDTOS.add(dynamicdto);
                break;
            case UNKNOWN:
                break;
            default:
                break;
        }
    }

    private void fillReplyDynamic(String corpid, List<DynamicDTO> dynamicDTOS, PaasFormDataEntityExt paasFormData, String creatorId, String replyName, String sendName, String phone, String memo, String content, Long time, Integer businessType) {
        if (Objects.isNull(paasFormData)) {
            return;
        }
        JSONObject data = paasFormData.getData();
        XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(businessType);
        switch (xbbRefTypeEnum) {
            case CUSTOMER_MANAGEMENT:
                Long customerId = paasFormData.getId();
                String customerName = data.getString(CustomerManagementEnum.NAME.getAttr());
                replyName = Objects.nonNull(customerName) ? customerName : replyName;
                DynamicDTO dynamicDTO = initDynamicDTO(creatorId, memo, ProjectLogEnum.CUSTOMER_SMS.getSubType(), DynamicDTO.initMemoHolder(replyName + ": " + phone, sendName, content), null, null, customerId);
                dynamicDTO.setAddTime(time);
                dynamicDTO.setCorpid(corpid);
                dynamicDTOS.add(dynamicDTO);
                break;
            case CONTACT:
                Long contactId = paasFormData.getId();
                String contactName = data.getString(ContactEnum.NAME.getAttr());
                replyName = Objects.nonNull(contactName) ? contactName : replyName;
                DynamicDTO dynamicdto = initDynamicDTO(creatorId, memo, ProjectLogEnum.CONTACT_SMS.getSubType(), DynamicDTO.initMemoHolder(replyName + ": " + phone, sendName, content), null, null, contactId);
                dynamicdto.setAddTime(time);
                dynamicdto.setCorpid(corpid);
                dynamicDTOS.add(dynamicdto);
                break;
            case UNKNOWN:
                break;
            default:
                break;
        }
    }
}
